<?php

namespace App\Repositories;

use App\Exceptions\BasicException;
use Illuminate\Support\Facades\DB;
use App\Enums\ErmEnum;
use Illuminate\Support\Facades\Redis;
use App\Enums\RedisKeyEnum;
use Log;

class ErmBlackRepository
{
    /*自动加黑*/
    public function autoAddBlack()
    {
        /*自动加黑*/
        $this->blackCheckPayId();
    }

    /*自动加黑*/
    public function blackCheckPayId()
    {
        $start_time = strtotime('monday this week');
        $end_time = time();
        $last_erm_pay_id_res = app("model_erm_pay_id_record")
            ->select('id')
            ->where([['create_time', '>=', $start_time], ['create_time', '<=', $end_time]])
            ->orderBy('id', 'desc')
            ->first();
        if (!$last_erm_pay_id_res) {
            return true;
        }

        $erm_pay_id_res = app("model_erm_pay_id_record")
            ->selectRaw('user_id,count(distinct pay_id) as pay_id_num,type')
//            ->with('erm_public_list:user_id,type')
            ->where([['create_time', '>=', $start_time], ['create_time', '<=', $end_time]])
            ->groupBy('user_id')
            ->groupBy('type')
            ->get()->toArray();
        if (!$erm_pay_id_res) {
            return true;
        }

        /*批量获取用户名单类型，1000条查询一次*/
        $ermPayUserIds = [];
        $ermPublicMap = [];
        $ermPayIdNum = count($erm_pay_id_res);
        foreach ($erm_pay_id_res as $k => $v) {
            $ermPayUserIds[] = $v['user_id'];
            if (count($ermPayUserIds) >= 500 || $ermPayIdNum <= $k + 1) {
                $ermPublicListRes = app("model_erm_public_list")->select('user_id', 'type')->whereIn('user_id', $ermPayUserIds)->get()->toArray();
                foreach ($ermPublicListRes as $key => $val) {
                    $ermPublicMap[$val['user_id']] = $val['type'];
                }
                unset($ermPayUserIds);
            }
        }
        if (empty($ermPublicMap)) {
            return true;
        }

        /*风控规则*/
        $wx_rule = $this->getConfig(ErmEnum::USER_WX_PAY_OPEN_ID_LIMIT_BLACK);
        $ali_rule = $this->getConfig(ErmEnum::USER_ALI_PAY_BUYER_ID_LIMIT_BLACK);

        /*加锁防止并发造成数据混乱，如果程序运行超时，锁定200秒*/
        $lock_second = 200;
        $lock_key = RedisKeyEnum::ERM_BLACK_CHECK_PAY_LOCK;
        $lock = Redis::setnx($lock_key, 1);
        if (!$lock) {
            throw new BasicException(100004);
        }
        Redis::expire($lock_key, $lock_second);

        DB::beginTransaction();
        try {
            // 本周最后一次移除黑名单的记录
            $erm_list_record_res = app("model_erm_list_record")->select(DB::raw('user_id,MAX(create_time) as create_time'))->where(['old_type' => ErmEnum::BLACK_TYPE, 'new_type' => ErmEnum::PUBLIC_TYPE, ['create_time', '>=', $start_time], ['create_time', '<=', $end_time]])->groupBy('user_id')->orderBy('id', 'desc')->get()->toArray();
            $erm_list_record_res = $erm_list_record_res ? array_column($erm_list_record_res, 'create_time', 'user_id') : [];

            foreach ($erm_pay_id_res as $k => $v) {
//                $type = $v['erm_public_list']['type'] ?? 1;
                $keyUserId = $v['user_id'];
                $type = $ermPublicMap[$keyUserId] ?? 1;
                // 只更改大众名单和灰名单用户
                // 白名单用户增加风控次数
                if (!in_array($type, [ErmEnum::PUBLIC_TYPE, ErmEnum::GRAY_TYPE, ErmEnum::WHITE_TYPE])) {
                    continue;
                }
                /*本周有移除黑名单的记录,重新查询移除记录后的数量*/
                // if (in_array($v['user_id'], $erm_list_record_users)) {
                if (isset($erm_list_record_res[$v['user_id']])) {
                    $v = app("model_erm_pay_id_record")
                        ->selectRaw('user_id,count(distinct pay_id) as pay_id_num,type')
                        ->with('erm_public_list:user_id,type')
                        ->where([['create_time', '>=', $erm_list_record_res[$v['user_id']]], ['create_time', '<=', $end_time]])
                        ->where('type', $v['type'])
                        ->where('user_id', $v['user_id'])
                        ->groupBy('user_id')
                        ->groupBy('type')
                        ->first();

                    if (!$v) {
                        continue;
                    }

                    $v = $v->toArray();
                }
                /*单人微信open_id可持有数量上限*/
                if ($v['type'] == 1 && !empty($wx_rule) && $v['pay_id_num'] > $wx_rule['value']) {
                    $public_list_res = app("model_erm_public_list")->where(['user_id' => $v['user_id']])->first();
                    if (in_array($public_list_res['type'], [ErmEnum::PUBLIC_TYPE, ErmEnum::GRAY_TYPE])) {
                        app('repo_erm_public_list')->joinListWay($v['user_id'], ErmEnum::BLACK_TYPE, '多个微信支付id');
                    }
                    if (in_array($public_list_res['type'], [ErmEnum::WHITE_TYPE])){
                        app('repo_erm_white')->triggerLimit($v['user_id']);
                    }
                }

                /*单人支付宝buyer_id可持有数量上限*/
                if ($v['type'] == 2 && !empty($ali_rule) && $v['pay_id_num'] > $ali_rule['value']) {
                    $public_list_res = app("model_erm_public_list")->where(['user_id' => $v['user_id']])->first();
                    if (in_array($public_list_res['type'], [ErmEnum::PUBLIC_TYPE, ErmEnum::GRAY_TYPE])) {
                        app('repo_erm_public_list')->joinListWay($v['user_id'], ErmEnum::BLACK_TYPE, '多个支付宝支付id');
                    }
                    if (in_array($public_list_res['type'], [ErmEnum::WHITE_TYPE])){
                        app('repo_erm_white')->triggerLimit($v['user_id']);
                    }
                }
            }

            DB::commit();
            // Db::rollBack();

            /*解锁*/
            Redis::del($lock_key);
        } catch (\Exception $e) {
            DB::rollBack();
            throw new BasicException(100003, $e->getMessage());
        }

        return true;
    }

    private function getConfig($key)
    {
        $rule = app('model_erm_config')->where([
            'status' => 0,
            'key' => $key,
        ])->first();

        return $rule;
    }
}
